package model

import (
	"fmt"
	"math"
	"strings"

	"dev.ixmxm.top/rms/config"
	"dev.ixmxm.top/rms/utils/angles"
	"dev.ixmxm.top/rms/utils/log"
	"dev.ixmxm.top/rms/utils/tools"
)

const (
	FloatLimit       = 1e-5
	Colinear         = 0
	Clockwise        = 1
	CounterClockwise = 2
)

type PathLocks []string

func (locks PathLocks) String() string {
	strs := make([]string, 0)
	for _, l := range locks {
		strs = append(strs, l)
	}
	return strings.Join(strs, ",")
}

func (locks *PathLocks) Add(lock string) {
	if locks == nil {
		*locks = make(PathLocks, 0)
	}
	for _, item := range *locks {
		if item == lock {
			return
		}
	}
	*locks = append(*locks, lock)
}
func (locks *PathLocks) Adds(newlocks []string) {
	if locks == nil {
		*locks = make(PathLocks, 0)
	}
	for _, item := range newlocks {
		if tools.StringSliceIsContain(*locks, item) {
			continue
		}
		*locks = append(*locks, item)
	}
}
func (locks PathLocks) ToIds() []string {
	res := make([]string, 0)
	for _, l := range locks {
		res = append(res, l)
	}
	return res
}

func (locks PathLocks) Conflict(otherLocks PathLocks) bool {
	for _, item := range locks {
		for _, ol := range otherLocks {
			if item == ol {
				return true
			}
		}
	}
	return false
}

type Pose2 struct {
	X float64 `bson:"x" json:"x"` //矩形端点1 X坐标
	Y float64 `bson:"y" json:"y"` //矩形端点1 Y坐标
}
type PoseArray []Pose2

type NomalTaskOccupy struct {
	isOccupy bool
	remark   string
}

func (nomalTaskOccupy NomalTaskOccupy) IsOccupy(isOccupy bool) {
	nomalTaskOccupy.isOccupy = isOccupy
}
func (nomalTaskOccupy *NomalTaskOccupy) GetOccupy() bool {
	return nomalTaskOccupy.isOccupy
}

//计算一个点是否在多边形内部
func (polygon PoseArray) PointInPolygon1(x, y float64) bool {
	count := 0
	p := Pose2{x, y}
	extreme := Pose2{math.MaxFloat64, y}

	for i := 0; i < len(polygon); i++ {
		next := (i + 1) % len(polygon)
		if doIntersect(p, extreme, polygon[i], polygon[next]) {
			if orientation(polygon[i], p, polygon[next]) == 0 && onSegment(polygon[i], p, polygon[next]) {
				return true
			}
			if math.Abs(p.Y-polygon[next].Y) <= FloatLimit && math.Abs(polygon[i].Y-polygon[next].Y) <= FloatLimit {
				continue
			}
			count++
		}
	}
	return count%2 == 1
}
func (polygon PoseArray) PointInPolygon(x, y float64) bool {
	isLeft := func(P0, P1, P Pose2) bool {
		var abc = ((P1.X-P0.X)*(P.Y-P0.Y) - (P.X-P0.X)*(P1.Y-P0.Y))
		if abc >= 0 {
			return true
		}
		return false
	}
	wn := 0
	currentPoint := Pose2{X: x, Y: y}
	for i, j := len(polygon)-1, 0; j < len(polygon); i, j = j, j+1 {
		if orientation(polygon[i], currentPoint, polygon[j]) == 0 && onSegment(polygon[i], currentPoint, polygon[j]) {
			return true
		}
		if polygon[i].Y <= currentPoint.Y {
			if polygon[j].Y > currentPoint.Y && isLeft(polygon[i], polygon[j], currentPoint) {
				wn += 1
			}
		} else {
			if polygon[j].Y <= currentPoint.Y && !isLeft(polygon[i], polygon[j], currentPoint) {
				wn -= 1
			}
		}
	}
	if wn == 0 {
		return false
	}
	return true
}

//假设pqr在一条直线，检查q是否在pr线段上
func onSegment(p, q, r Pose2) bool {
	if q.X <= math.Max(p.X, r.X) && q.X >= math.Min(p.X, r.X) && q.Y <= math.Max(p.Y, r.Y) && q.Y >= math.Min(p.Y, r.Y) {
		return true
	}
	return false
}

func Max(x, y int64) int64 {
	if x >= y {
		return x
	} else {
		return y
	}
}

func Min(x, y int64) int64 {
	if x <= y {
		return x
	} else {
		return y
	}
}

//pqr三点的顺序，0->一条直线 1->顺时针 2->逆时针
func orientation(p, q, r Pose2) int {
	val := (q.Y-p.Y)*(r.X-q.X) - (q.X-p.X)*(r.Y-q.Y)
	if val <= FloatLimit && val >= -FloatLimit {
		return Colinear
	} else if val > FloatLimit {
		return Clockwise
	} else {
		return CounterClockwise
	}
}

//检查p1q1和p2q2是否相交
func doIntersect(p1, q1, p2, q2 Pose2) bool {
	o1 := orientation(p1, q1, p2)
	o2 := orientation(p1, q1, q2)
	o3 := orientation(p2, q2, p1)
	o4 := orientation(p2, q2, q1)

	if o1 != o2 && o3 != o4 {
		return true
	}
	if o1 == Colinear && onSegment(p1, p2, q1) {
		return true
	}

	if o2 == Colinear && onSegment(p1, q2, q1) {
		return true
	}

	if o3 == Colinear && onSegment(p2, p1, q2) {
		return true
	}

	if o4 == Colinear && onSegment(p2, q1, q2) {
		return true
	}

	return false
}

//ConflictPolygon 判断多边形是否发相交
func (sPolygon PoseArray) ConflictPolygon(tPolygon PoseArray) bool {
	//判断边是否相交
	for index, p := range tPolygon {
		//判断是否是包含关系
		if sPolygon.PointInPolygon(p.X, p.Y) {
			return true
		}

		pNextIndex := index + 1
		if pNextIndex >= len(tPolygon) {
			pNextIndex = 0
		}
		pNext := tPolygon[pNextIndex]
		for sIndex, tp := range sPolygon {
			//判断是否是包含关系
			if tPolygon.PointInPolygon(tp.X, tp.Y) {
				return true
			}

			tpNextIndex := sIndex + 1
			if tpNextIndex >= len(sPolygon) {
				tpNextIndex = 0
			}
			tpNext := sPolygon[tpNextIndex]
			if doIntersect(p, pNext, tp, tpNext) {
				return true
			}
		}
	}
	return false
}
func (sPolygon PoseArray) pathBlockCircle(x, y, radius float64) bool {
	for index, p1 := range sPolygon {
		pNextIndex := index + 1
		if pNextIndex >= len(sPolygon) {
			pNextIndex = 0
		}
		p2 := sPolygon[pNextIndex]
		xa, ya, xb, yb := p1.X, p1.Y, p2.X, p2.Y
		line_dis := 99999.0
		if (xb-xa)*(x-xa)+(yb-ya)*(y-ya) < 0 {
			line_dis = math.Sqrt((xa-x)*(xa-x) + (ya-y)*(ya-y))
		} else if (xa-xb)*(x-xb)+(ya-yb)*(y-yb) < 0 {
			line_dis = math.Sqrt((xb-x)*(xb-x) + (yb-y)*(yb-y))
		} else {
			if xa == xb {
				line_dis = math.Abs(x - xa)
			} else if ya == yb {
				line_dis = math.Abs(y - ya)
			} else {
				k := (yb - ya) / (xb - xa)
				b := yb - k*xb
				line_dis = math.Abs(k*x-y+b) / math.Sqrt(k*k+1)
			}
		}
		if line_dis < radius {
			return true
		}
	}
	return false
}

type TrafficPaths []*TrafficPath

func (paths TrafficPaths) String() string {
	strs := make([]string, 0)
	for _, p := range paths {
		strs = append(strs, p.String())
	}
	return strings.Join(strs, " && ")
}

func (paths TrafficPaths) ToIDs() []string {
	res := make([]string, 0)
	for _, p := range paths {
		res = append(res, p.PathId)
	}
	return res
}

func (paths TrafficPaths) ToRotationTypes() []int {
	res := make([]int, 0)
	for _, p := range paths {
		res = append(res, p.RotateType)
	}
	return res
}

func (paths TrafficPaths) Front() *TrafficPath {
	if len(paths) < 1 {
		return nil
	}
	return paths[0]
}

func (paths TrafficPaths) Back() *TrafficPath {
	if len(paths) < 1 {
		return nil
	}
	return paths[len(paths)-1]
}

func (paths *TrafficPaths) PopFront() {
	if len(*paths) < 1 {
		return
	}
	*paths = (*paths)[1:]
}

func (paths *TrafficPaths) GotPathTarget(id string, agv Node) Node {
	if len(*paths) < 1 {
		return agv
	}
	for _, item := range *paths {
		if item.PathId == id {
			return item.GetTarget()
		}
	}
	return agv
}

func (paths *TrafficPaths) PopN(id string) {
	if len(*paths) < 1 {
		return
	}
	for index, item := range *paths {
		if item.PathId != id {
			continue
		}
		if index <= len(*paths)-2 {
			*paths = (*paths)[index+1:]
			return
		}
		if index == len(*paths)-1 {
			*paths = []*TrafficPath{}
			return
		}
	}
	//log.Panicf("PopN error:get %d,have:%v", id, paths.ToIDs())
	log.Error("PopN error:get %d,have:%v", id, paths.ToIDs())
}

func (paths TrafficPaths) HasPath(id string) (*TrafficPath, bool) {
	for _, p := range paths {
		if p.PathId == id {
			return p, true
		}
	}
	return nil, false
}

func (paths *TrafficPaths) AllBlocks() PathLocks {
	res := make(PathLocks, 0)
	for _, item := range *paths {
		res = append(res, item.AllBlocks()...)
	}
	//function.SliceUnique(&res)
	return res
}

//Conflict 判断路径是否冲突，返回冲突的锁定点编号
func (paths *TrafficPaths) Conflict(path *TrafficPath) (bool, string) {
	for _, item := range *paths {
		if item.PathId == path.PathId {
			//路径冲突
			return true, item.PathId
		}

		if item.NodeA.Id == path.NodeA.Id || item.NodeA.Id == path.NodeB.Id || item.NodeB.Id == path.NodeA.Id || item.NodeB.Id == path.NodeB.Id {
			//路径端点被人使用
			return true, item.PathId
		}
		//路径锁定点冲突
		if item.AllBlocks().Conflict(path.AllBlocks()) {
			return true, item.PathId
		}
		if item.PathPolygon.ConflictPolygon(path.PathPolygon) {
			return true, item.PathId
		}
	}
	return false, ""
}

//TrafficPath PathBlocks:路径锁，SourceBlocks：起点锁，TargetBlocks：终点锁
type TrafficPath struct {
	Path                              //路径
	PathBlocks          PathLocks     `bson:"path_blocks"`          //路径锁
	SourceBlocks        PathLocks     `bson:"source_blocks"`        //起点锁
	TargetBlocks        PathLocks     `bson:"target_blocks"`        //终点锁
	PathPolygon         PoseArray     `bson:"path_polygon"`         //路径多边形
	BodyDir             BodyDirection `bson:"body_dir"`             //车身方向
	RotateType          int           `bson:"rotation_type"`        //0=不旋转、1=逆时针旋转、-1=顺时针旋转
	RotateStartAng      int           `bson:"rotation_start"`       //起始旋转角度
	RotateEndAng        int           `bson:"rotation_end"`         //终止旋转角度
	PathEndAng          int           `bson:"path_end"`             //路径终止角度
	TargetRotate        int           `bson:"target_rotation_type"` //0=不旋转、1=逆时针旋转、-1=顺时针旋转
	NextPathAng         int           `bson:"next_path_ang"`        //下条路径起始角度
	BindDeadWayId       string        //关联的死胡同
	BindPathMutexAreaId string        //关联的允许路线对冲区域

}

func (path TrafficPath) String() string {
	return fmt.Sprintf("path_id:%s,pb:[%s],sb:[%s],tb:[%s]", path.Path.PathId, path.PathBlocks.String(), path.SourceBlocks.String(), path.TargetBlocks.String())
}

func (path *TrafficPath) AllBlocks() PathLocks {
	res := make(PathLocks, 0)
	res = append(res, path.PathBlocks...)
	res = append(res, path.SourceBlocks...)
	res = append(res, path.TargetBlocks...)
	//function.SliceUnique(&res)
	return res
}

// 获取路径多边形的边界范围
func (path *TrafficPath) GetPolygonRangeXY() (minX float64, maxX float64, minY float64, maxY float64) {
	minX = path.PathPolygon[0].X
	maxX = path.PathPolygon[0].X
	minY = path.PathPolygon[0].Y
	maxY = path.PathPolygon[0].Y

	for _, p := range path.PathPolygon {
		if p.X < minX {
			minX = p.X
		}

		if p.X > maxX {
			maxX = p.X
		}

		if p.Y < minY {
			minY = p.Y
		}

		if p.Y > maxY {
			maxY = p.Y
		}
	}
	return minX, maxX, minY, maxY
}

type GlobalPath struct {
	Sn         string       `bson:"sn"`
	MapName    string       `bson:"map_name"`
	Cost       float64      `bson:"cost"`
	Paths      TrafficPaths `bson:"paths"`
	Target     string       `bson:"target"`
	EndBlocks  PathLocks    `bson:"end_blocks"`
	BlockStart string       `bson:"block_start`
}

func (GlobalPath) TableName() string {
	return "t_running_global_paths"
}

func (gp *GlobalPath) IsFinalGoal() bool {
	if gp.Paths.Back() == nil {
		return true
	}
	return gp.Paths.Back().GetTarget().Id == gp.Target
}

//FrontList 获得前size段全局路径，且总长度小于length，如果单条路径长度唱过length，则返回一条路径
func (gp *GlobalPath) FrontList(size int, length int64, deadWayAreas []Area, tideAreas []Area, allowPathMutexAreas []Area) TrafficPaths {
	//先获得正常局部路径的下标
	trafficPaths := gp.FrontListReal(size, length, deadWayAreas, tideAreas, allowPathMutexAreas)
	return trafficPaths
}

//FrontList 获得前size段全局路径，且总长度小于length，如果单条路径长度唱过length，则返回一条路径
func (gp *GlobalPath) FrontListReal(size int, length int64, deadWayAreas []Area, tideAreas []Area, allowPathMutexAreas []Area) TrafficPaths {
	tools.Assert(size > 0, "global front size = 0")
	IsContaion := func(allSiteIds []string, currentSiteId string) bool {
		for _, id := range allSiteIds {
			if currentSiteId == id {
				return true
			}
		}
		return false
	}
	findTrafficPathAreaId := func(deadWayArea1s, allowPathMutexArea1s []Area, l *TrafficPath) bool {
		findDeadWayAreaId, findAllowPathMutexAreaId := "", ""
		findObj := false
		if len(deadWayArea1s) > 0 {
			for _, deadArea := range deadWayArea1s {
				if IsContaion(deadArea.ContainDotIds, l.GetSource().Id) {
					findDeadWayAreaId = deadArea.Id
					findObj = true
					break
				}
			}
		}
		if len(allowPathMutexArea1s) > 0 {
			for _, allowPathMutexArea := range allowPathMutexArea1s {
				if IsContaion(allowPathMutexArea.ContainDotIds, l.GetSource().Id) {
					findAllowPathMutexAreaId = allowPathMutexArea.Id
					findObj = true
					break
				}
				if IsContaion(allowPathMutexArea.ContainDotIds, l.GetTarget().Id) {
					findAllowPathMutexAreaId = allowPathMutexArea.Id
					findObj = true
					break
				}
			}
		}
		l.BindDeadWayId = findDeadWayAreaId
		l.BindPathMutexAreaId = findAllowPathMutexAreaId
		return findObj
	}

	//记录局部路径锁经过的死胡同
	res := TrafficPaths{}
	lastFindTide := false
	totalLength := float64(0)
	for _, l := range gp.Paths {
		totalLength += l.PathLength
		//1.允许路线对冲区域 2.死胡同区域的处理方法
		find := findTrafficPathAreaId(deadWayAreas, allowPathMutexAreas, l)
		if find {
			res = append(res, l)
			lastFindTide = false
			continue
		}
		//1.起点不在潮汐，终点在潮汐 OR 2.起点在潮汐但是终点不在潮汐  =>加一条路经
		if len(tideAreas) > 0 {
			findTide := false
			for _, tideArea := range tideAreas {
				if !IsContaion(tideArea.ContainDotIds, l.GetSource().Id) && IsContaion(tideArea.ContainDotIds, l.GetTarget().Id) {
					res = append(res, l)
					findTide = true
					lastFindTide = true
					break
				} else if IsContaion(tideArea.ContainDotIds, l.GetSource().Id) && !IsContaion(tideArea.ContainDotIds, l.GetTarget().Id) {
					res = append(res, l)
					findTide = true
					lastFindTide = false
					break
				}
			}
			if findTide {
				continue
			}
		}
		if len(res) < size && totalLength < float64(length) {
			lastFindTide = false
			res = append(res, l)
		} else if len(res) < config.Conf.MinPathLimitNum {
			lastFindTide = false
			res = append(res, l)
		} else if l.Type == PathTypeBezier {
			lastFindTide = false
			res = append(res, l)
		} else if lastFindTide {
			lastFindTide = false
			res = append(res, l)
			break
		} else {
			break
		}
	}
	if size > 0 && len(res) == 0 {
		if len(gp.Paths) > 0 {
			res = append(res, gp.Paths[0])
		}
	}
	return res
}

type LocalPath struct {
	Sn           string       `bson:"sn"`
	MapName      string       `bson:"map_name"`
	Paths        TrafficPaths `bson:"paths"`
	CurrentNode  Node         `bson:"node"`
	NodeRect     PoseArray    `bson:"node_rect"`
	RotateRadius float64      `bson:"rotate_radius"`
	BackRadius   float64      `bson:"back_radius"`
	RobotAng     float64      `bson:"robot_ang"`
	SpecialLocks PathLocks    `bson:"special_locks"`
}

//inAngleRangeCheck 加入路径起点的旋转类型，判断targetTheta是否在startTheta，endTheta范围内,输入均为角度
func inAngleRangeChec(startTheta, endTheta, targetTheta, rotate_type int) bool {
	if startTheta > endTheta {
		if targetTheta < startTheta && targetTheta > endTheta {
			if rotate_type == -1 {
				return true
			}
		} else {
			if rotate_type == 1 {
				return true
			}
		}
	} else {
		if targetTheta < endTheta && targetTheta > startTheta {
			if rotate_type == 1 {
				return true
			}
		} else {
			if rotate_type == -1 {
				return true
			}
		}
	}
	return false
}
func blockCircle(path *TrafficPath, p1, p2 Pose2, radius float64) (bool, bool) {
	if path.RotateType != 0 {
		if blockStartCircle(path, p1, p2, radius) {
			return true, true
		}
	}
	if path.TargetRotate != 0 {
		return blockEndCircle(path, p1, p2, radius), false
	}
	return false, true
}

func blockBackCircle(path *TrafficPath, p1, p2 Pose2, radius float64) (bool, bool) {
	if path.RotateType != 0 {
		if blockStartBackCircle(path, p1, p2, radius) {
			return true, true
		}
	}
	if path.TargetRotate != 0 {
		return blockEndBackCircle(path, p1, p2, radius), false
	}
	return false, true
}

func blockStartBackCircle(path *TrafficPath, p1, p2 Pose2, radius float64) bool {
	node := path.GetSource()
	x, y := float64(node.X), float64(node.Y)
	xa, ya, xb, yb := p1.X, p1.Y, p2.X, p2.Y
	line_dis := 99999.0
	nearest_x, nearest_y := 0.0, 0.0
	if (xb-xa)*(x-xa)+(yb-ya)*(y-ya) < 0 {
		line_dis = math.Sqrt((xa-x)*(xa-x) + (ya-y)*(ya-y))
		nearest_x, nearest_y = xa, ya
	} else if (xa-xb)*(x-xb)+(ya-yb)*(y-yb) < 0 {
		line_dis = math.Sqrt((xb-x)*(xb-x) + (yb-y)*(yb-y))
		nearest_x, nearest_y = xb, yb
	} else {
		if xa == xb {
			line_dis = math.Abs(x - xa)
			nearest_x, nearest_y = xa, y
		} else if ya == yb {
			line_dis = math.Abs(y - ya)
			nearest_x, nearest_y = x, ya
		} else {
			k := (yb - ya) / (xb - xa)
			b := yb - k*xb
			line_dis = math.Abs(k*x-y+b) / math.Sqrt(k*k+1)
			//两条垂直相交直线的斜率相乘积为-1：k1*k2=-1.
			// y0=k*x0+b 与 (y-y0)/(x-x0) = -1/k，已知x,y,求x0,y0
			nearest_x = (k*y + x - k*b) / (k*k + 1)
			nearest_y = k*nearest_x + b
		}
	}
	theta := int(math.Atan2(nearest_y-y, nearest_x-x) * 180.0 / math.Pi)
	if theta < 0 {
		theta = theta + 360
	}
	if line_dis < radius && inAngleRangeChec(path.RotateStartAng+180, path.RotateEndAng+180, theta, path.RotateType) {
		return true
	}
	return false
}
func blockEndBackCircle(path *TrafficPath, p1, p2 Pose2, radius float64) bool {
	node := path.GetTarget()
	x, y := float64(node.X), float64(node.Y)
	xa, ya, xb, yb := p1.X, p1.Y, p2.X, p2.Y
	line_dis := 99999.0
	nearest_x, nearest_y := 0.0, 0.0
	if (xb-xa)*(x-xa)+(yb-ya)*(y-ya) < 0 {
		line_dis = math.Sqrt((xa-x)*(xa-x) + (ya-y)*(ya-y))
		nearest_x, nearest_y = xa, ya
	} else if (xa-xb)*(x-xb)+(ya-yb)*(y-yb) < 0 {
		line_dis = math.Sqrt((xb-x)*(xb-x) + (yb-y)*(yb-y))
		nearest_x, nearest_y = xb, yb
	} else {
		if xa == xb {
			line_dis = math.Abs(x - xa)
			nearest_x, nearest_y = xa, y
		} else if ya == yb {
			line_dis = math.Abs(y - ya)
			nearest_x, nearest_y = x, ya
		} else {
			k := (yb - ya) / (xb - xa)
			b := yb - k*xb
			line_dis = math.Abs(k*x-y+b) / math.Sqrt(k*k+1)
			//两条垂直相交直线的斜率相乘积为-1：k1*k2=-1.
			// y0=k*x0+b 与 (y-y0)/(x-x0) = -1/k，已知x,y,求x0,y0
			nearest_x = (k*y + x - k*b) / (k*k + 1)
			nearest_y = k*nearest_x + b
		}
	}
	theta := int(math.Atan2(nearest_y-y, nearest_x-x) * 180.0 / math.Pi)
	if theta < 0 {
		theta = theta + 360
	}
	if line_dis < radius && inAngleRangeChec(path.PathEndAng+180, path.NextPathAng+180, theta, path.TargetRotate) {
		return true
	}
	return false
}

func blockStartCircle(path *TrafficPath, p1, p2 Pose2, radius float64) bool {
	node := path.GetSource()
	x, y := float64(node.X), float64(node.Y)
	xa, ya, xb, yb := p1.X, p1.Y, p2.X, p2.Y
	line_dis := 99999.0
	nearest_x, nearest_y := 0.0, 0.0
	if (xb-xa)*(x-xa)+(yb-ya)*(y-ya) < 0 {
		line_dis = math.Sqrt((xa-x)*(xa-x) + (ya-y)*(ya-y))
		nearest_x, nearest_y = xa, ya
	} else if (xa-xb)*(x-xb)+(ya-yb)*(y-yb) < 0 {
		line_dis = math.Sqrt((xb-x)*(xb-x) + (yb-y)*(yb-y))
		nearest_x, nearest_y = xb, yb
	} else {
		if xa == xb {
			line_dis = math.Abs(x - xa)
			nearest_x, nearest_y = xa, y
		} else if ya == yb {
			line_dis = math.Abs(y - ya)
			nearest_x, nearest_y = x, ya
		} else {
			k := (yb - ya) / (xb - xa)
			b := yb - k*xb
			line_dis = math.Abs(k*x-y+b) / math.Sqrt(k*k+1)
			//两条垂直相交直线的斜率相乘积为-1：k1*k2=-1.
			// y0=k*x0+b 与 (y-y0)/(x-x0) = -1/k，已知x,y,求x0,y0
			nearest_x = (k*y + x - k*b) / (k*k + 1)
			nearest_y = k*nearest_x + b
		}
	}
	theta := int(math.Atan2(nearest_y-y, nearest_x-x) * 180.0 / math.Pi)
	if theta < 0 {
		theta = theta + 360
	}
	if line_dis < radius && inAngleRangeChec(path.RotateStartAng, path.RotateEndAng, theta, path.RotateType) {
		return true
	}
	return false
}
func blockEndCircle(path *TrafficPath, p1, p2 Pose2, radius float64) bool {
	node := path.GetTarget()
	x, y := float64(node.X), float64(node.Y)
	xa, ya, xb, yb := p1.X, p1.Y, p2.X, p2.Y
	line_dis := 99999.0
	nearest_x, nearest_y := 0.0, 0.0
	if (xb-xa)*(x-xa)+(yb-ya)*(y-ya) < 0 {
		line_dis = math.Sqrt((xa-x)*(xa-x) + (ya-y)*(ya-y))
		nearest_x, nearest_y = xa, ya
	} else if (xa-xb)*(x-xb)+(ya-yb)*(y-yb) < 0 {
		line_dis = math.Sqrt((xb-x)*(xb-x) + (yb-y)*(yb-y))
		nearest_x, nearest_y = xb, yb
	} else {
		if xa == xb {
			line_dis = math.Abs(x - xa)
			nearest_x, nearest_y = xa, y
		} else if ya == yb {
			line_dis = math.Abs(y - ya)
			nearest_x, nearest_y = x, ya
		} else {
			k := (yb - ya) / (xb - xa)
			b := yb - k*xb
			line_dis = math.Abs(k*x-y+b) / math.Sqrt(k*k+1)
			//两条垂直相交直线的斜率相乘积为-1：k1*k2=-1.
			// y0=k*x0+b 与 (y-y0)/(x-x0) = -1/k，已知x,y,求x0,y0
			nearest_x = (k*y + x - k*b) / (k*k + 1)
			nearest_y = k*nearest_x + b
		}
	}
	theta := int(math.Atan2(nearest_y-y, nearest_x-x) * 180.0 / math.Pi)
	if theta < 0 {
		theta = theta + 360
	}
	if line_dis < radius && inAngleRangeChec(path.PathEndAng, path.NextPathAng, theta, path.TargetRotate) {
		return true
	}
	return false
}
func (lp *TrafficPath) RotateConflictRect(path *LocalPath, radius float64) (bool, bool, *TrafficPath) {
	var conflictPath *TrafficPath
	if path.Paths == nil || path.RotateRadius == 0.0 {
		return false, false, nil
	}
	rotateConflict, isStart := false, false
	for k := len(path.Paths) - 1; k >= 0; k-- {
		p := path.Paths[k]
		// for _, p := range path.Paths {
		if (p.RotateType != 0 && p.SourceBlocks != nil) || p.TargetRotate != 0 {
			for i := 0; i <= len(lp.PathPolygon)-1; i++ {
				ni := i + 1
				if i == len(lp.PathPolygon)-1 {
					ni = 0
				}
				if rotateConflict, isStart = blockCircle(p, lp.PathPolygon[i], lp.PathPolygon[ni], radius); rotateConflict {
					conflictPath = p
					break
				}
			}
			if rotateConflict {
				break
			}
			//todo1-2
			if p.RotateType != 0 && p.GetSource().Type == NodePath {
				rotateConflict = lp.PathPolygon.pathBlockCircle(float64(p.GetSource().X), float64(p.GetSource().Y), path.BackRadius)
				isStart = true
				conflictPath = p
			}
		}
	}
	return rotateConflict, isStart, conflictPath
}

func (lp *LocalPath) RotateConflictRect(path *TrafficPath, robot *Robot) (bool, bool) {
	radius := robot.Type.GetRobotRotateRadius(robot)
	radiusBack := robot.Type.GetRobotBackRotateRadius(robot)
	rotateConflict, isStart := false, false
	if path.RotateType != 0 || path.TargetRotate != 0 {
		for i := 0; i <= len(lp.NodeRect)-1; i++ {
			ni := i + 1
			if i == len(lp.NodeRect)-1 {
				ni = 0
			}
			//路径头部点,车头部旋转作为计算标准
			if rotateConflict, isStart = blockCircle(path, lp.NodeRect[i], lp.NodeRect[ni], radius); rotateConflict {
				return rotateConflict, isStart
			}

			//路径头部点,车头部旋转作为计算标准
			if rotateConflict, isStart = blockBackCircle(path, lp.NodeRect[i], lp.NodeRect[ni], radiusBack); rotateConflict {
				return rotateConflict, isStart
			}
		}
		if path.TargetRotate != 0 {
			rect := robot.Type.GotLockRectangle(robot, angles.Deg2Rad(float64(path.NextPathAng)), float64(path.Path.GetTarget().X), float64(path.Path.GetTarget().Y), 0, path.Path.GetTarget().Type, false, false)
			if lp.NodeRect.ConflictPolygon(rect) {
				return true, false
			}
		}
		for _, p := range lp.Paths {
			for i := 0; i <= len(p.PathPolygon)-1; i++ {
				ni := i + 1
				if i == len(p.PathPolygon)-1 {
					ni = 0
				}
				if rotateConflict, isStart = blockCircle(path, p.PathPolygon[i], p.PathPolygon[ni], radius); rotateConflict {
					return rotateConflict, isStart
				}
			}
		}
	}
	return rotateConflict, isStart
}

func (lp *LocalPath) LocationFrontRotateConflictRect(location123 *Location, locationFrontPoint Node, relationLocationMap map[string]Location, radius float64) bool {
	isContain := func(all []string, str string) bool {
		for _, va := range all {
			if va == str {
				return true
			}
		}
		return false
	}
	// isPolygonConflict, rotateConflict, siteConflict := false, false, false
	rotateConflict := false
	//判断当前是否在棒棒糖根部
	rejectIDs := make([]string, 0)
	rejectIDs = append(rejectIDs, location123.DepthPointId...)
	rejectIDs = append(rejectIDs, location123.FrontPointId)
	rejectIDs = append(rejectIDs, location123.ContainDotIds...)

	//关联地堆库根部锁点
	for _, otherLocation := range relationLocationMap {
		// rejectIDs = append(rejectIDs, otherLocation.ContainDotIds...)
		rejectIDs = append(rejectIDs, otherLocation.DepthPointId...)
		rejectIDs = append(rejectIDs, location123.FrontPointId)
	}

	// //局部路径剔除点
	allreadyLocalPathRejects := make([]string, 0)
	if lp.Paths != nil {
		for _, value := range lp.Paths {
			allreadyLocalPathRejects = append(allreadyLocalPathRejects, value.AllBlocks().ToIds()...)
		}
	}
	if lp.SpecialLocks != nil {
		allreadyLocalPathRejects = append(allreadyLocalPathRejects, lp.SpecialLocks.ToIds()...)
	}
	//判断根部点位是否冲突
	for _, rejectNodeId := range allreadyLocalPathRejects {
		if isContain(rejectIDs, rejectNodeId) {
			// siteConflict = true
			return true
		}
	}
	// if need_check_poly {
	// 	//判断当前根部多边形轮廓
	// 	if lp.CurrentNode.Id != "0" && lp.CurrentNode.Id != "" {
	// 		if lp.NodeRect.ConflictPolygon(location123.PolygonDraw) {
	// 			// isPolygonConflict = true
	// 			return true
	// 		}
	// 	}
	// 	//判断当前是否在棒棒糖头部
	// 	for i := 0; i <= len(lp.NodeRect)-1; i++ {
	// 		if i == len(lp.NodeRect)-1 {
	// 			if rotateConflict = blockFrontLocationCircle(locationFrontPoint, lp.NodeRect[len(lp.NodeRect)-1], lp.NodeRect[0], radius); rotateConflict {
	// 				break
	// 			}
	// 		} else {
	// 			if rotateConflict = blockFrontLocationCircle(locationFrontPoint, lp.NodeRect[i], lp.NodeRect[i+1], radius); rotateConflict {
	// 				break
	// 			}
	// 		}
	// 	}
	// }
	return rotateConflict
}

func blockFrontLocationCircle(node Node, p1, p2 Pose2, radius float64) bool {
	// node := path.GetSource()
	x, y := float64(node.X), float64(node.Y)
	xa, ya, xb, yb := p1.X, p1.Y, p2.X, p2.Y
	line_dis := 99999.0
	// nearest_x, nearest_y := 0.0, 0.0
	if (xb-xa)*(x-xa)+(yb-ya)*(y-ya) < 0 {
		line_dis = math.Sqrt((xa-x)*(xa-x) + (ya-y)*(ya-y))
		// nearest_x, nearest_y = xa, ya
	} else if (xa-xb)*(x-xb)+(ya-yb)*(y-yb) < 0 {
		line_dis = math.Sqrt((xb-x)*(xb-x) + (yb-y)*(yb-y))
		// nearest_x, nearest_y = xb, yb
	} else {
		if xa == xb {
			line_dis = math.Abs(x - xa)
			// nearest_x, nearest_y = xa, y
		} else if ya == yb {
			line_dis = math.Abs(y - ya)
			// nearest_x, nearest_y = x, ya
		} else {
			k := (yb - ya) / (xb - xa)
			b := yb - k*xb
			line_dis = math.Abs(k*x-y+b) / math.Sqrt(k*k+1)
			//两条垂直相交直线的斜率相乘积为-1：k1*k2=-1.
			// y0=k*x0+b 与 (y-y0)/(x-x0) = -1/k，已知x,y,求x0,y0
			// nearest_x = (k*y + x - k*b) / (k*k + 1)
			// nearest_y = k*nearest_x + b
		}
	}
	// theta := int(math.Atan2(nearest_y-y, nearest_x-x) * 180.0 / math.Pi)
	// if theta < 0 {
	// 	theta = theta + 360
	// }
	if line_dis < radius {
		return true
	}
	return false
}

type GetNodeCallBack func(id string) Node

func (need *TrafficPath) LocationFrontRotateConflictRect(location123 *Location, locationFrontPoint Node, relationLocationMap map[string]Location, radius float64, GetNode GetNodeCallBack) bool {
	isContain := func(all []string, str string) bool {
		for _, va := range all {
			if va == str {
				return true
			}
		}
		return false
	}
	// isPolygonConflict, rotateConflict, siteConflict := false, false, false
	rotateConflict := false
	//判断当前是否在棒棒糖根部
	rejectIDs := make([]string, 0)
	rejectIDs = append(rejectIDs, location123.DepthPointId...)
	rejectIDs = append(rejectIDs, location123.FrontPointId)
	//关联地堆库根部锁点
	for _, otherLocation := range relationLocationMap {
		// rejectIDs = append(rejectIDs, otherLocation.ContainDotIds...)
		rejectIDs = append(rejectIDs, otherLocation.DepthPointId...)
		rejectIDs = append(rejectIDs, location123.FrontPointId)
	}
	// //局部路径剔除点
	allreadyLocalPathRejects := need.AllBlocks().ToIds()
	//判断根部点位是否冲突
	for _, rejectNodeId := range allreadyLocalPathRejects {
		if isContain(rejectIDs, rejectNodeId) {
			// siteConflict = true
			return true
		}
	}
	//判断当前是否在棒棒糖头部
	// for i := 0; i <= len(need.PathPolygon)-1; i++ {
	// 	if i == len(need.PathPolygon)-1 {
	// 		if rotateConflict = blockFrontLocationCircle(locationFrontPoint, need.PathPolygon[len(need.PathPolygon)-1], need.PathPolygon[0], radius); rotateConflict {
	// 			break
	// 		}
	// 	} else {
	// 		if rotateConflict = blockFrontLocationCircle(locationFrontPoint, need.PathPolygon[i], need.PathPolygon[i+1], radius); rotateConflict {
	// 			break
	// 		}
	// 	}
	// }
	rotationConflictFun := func(frontNode Node) bool {
		rotateConflict1 := false
		for i := 0; i <= len(need.PathPolygon)-1; i++ {
			if i == len(need.PathPolygon)-1 {
				if rotateConflict1 = blockFrontLocationCircle(frontNode, need.PathPolygon[len(need.PathPolygon)-1], need.PathPolygon[0], radius); rotateConflict1 {
					break
				}
			} else {
				if rotateConflict1 = blockFrontLocationCircle(frontNode, need.PathPolygon[i], need.PathPolygon[i+1], radius); rotateConflict1 {
					break
				}
			}
		}
		return rotateConflict1
	}
	rotateConflict = rotationConflictFun(locationFrontPoint)
	//判断关联圆
	if !rotateConflict {
		for _, otherLocation := range relationLocationMap {
			tempFrontNode := GetNode(otherLocation.FrontPointId)
			rotateConflict = rotationConflictFun(tempFrontNode)
			if rotateConflict {
				break
			}
		}
	}

	return rotateConflict
}

type GetConnectPaths func(node Node) []Path

func (lp *LocalPath) Conflict(path *TrafficPath, callBack GetConnectPaths, needCalc bool, robot *Robot) (bool, string) {

	IsConnectStation := func(currentNode Node) bool {
		connectPaths := callBack(currentNode)
		for _, connectPath := range connectPaths {
			connectNode := connectPath.GetAnother(currentNode)
			if connectNode.Type == NodeStation {
				return true
			}
		}
		return false
	}
	//获得所有工位前一个点
	GetFrontNodes := func(currentNode Node) map[string]Node {
		retFronts := make(map[string]Node, 0)
		connectPaths := callBack(currentNode)
		for _, connectPath := range connectPaths {
			connectNode := connectPath.GetAnother(currentNode)
			retFronts[connectNode.Id] = connectNode
		}
		return retFronts
	}

	isRectangleConflict, isBackRotateConflict := false, false
	if lp.SpecialLocks != nil {
		if lp.SpecialLocks.Conflict(path.AllBlocks()) {
			return true, ""
		}
	}
	//需要计算车前方加上缓冲位置是
	copyPath := new(TrafficPath)
	err123 := tools.DeepCopy(path, &copyPath)
	//拷贝新的路径对象判断是否冲突
	if err123 != nil {
		return true, ""
	}

	if config.Conf.UseHeadCatch && needCalc && path.Type == PathTypeLine && robot != nil {
		rotateRad := robot.Type.GetRobotRotateRadius(robot)
		//扩展缓冲区域
		// l0 := float64(path.GetSource().Distance(path.GetTarget()))                                                   //路径长度（线段长度）
		// x0, y0 := float64(path.GetSource().X+path.GetTarget().X)/2, float64(path.GetSource().Y+path.GetTarget().Y)/2 //路径中点
		var theta float64
		switch {
		case path.BodyDirec == HeadAB || path.BodyDirec == Head && path.Dir == DirectionA2B:
			theta = math.Atan2(float64(path.NodeB.Y-path.NodeA.Y), float64(path.NodeB.X-path.NodeA.X))
		case path.BodyDirec == HeadBA || path.BodyDirec == Head && path.Dir == DirectionB2A:
			theta = math.Atan2(float64(path.NodeA.Y-path.NodeB.Y), float64(path.NodeA.X-path.NodeB.X))
		default:
			// panic("not here")
			return true, ""
		}
		//获得加上缓冲区域,判断是否冲突

		//按照角度加上
		x0, y0 := path.PathPolygon[0].X+rotateRad*math.Cos(theta), path.PathPolygon[0].Y+rotateRad*math.Sin(theta)
		x3, y3 := path.PathPolygon[3].X+rotateRad*math.Cos(theta), path.PathPolygon[3].Y+rotateRad*math.Sin(theta)

		copyPath.PathPolygon[0] = Pose2{X: x0, Y: y0}
		copyPath.PathPolygon[3] = Pose2{X: x3, Y: y3}

	}
	if lp.CurrentNode.Id != "0" && lp.CurrentNode.Id != "" {
		//
		if lp.NodeRect.ConflictPolygon(copyPath.PathPolygon) {
			isRectangleConflict = true
			// } else if lp.CurrentNode.Type == NodePath && !IsConnectStation(lp.CurrentNode) { //增加连接点没有库位的判断（主干道才进行小圆判断）
		} else if lp.CurrentNode.Type == NodePath {
			//判断当前路径是倒着走不考虑小圆
			isTailGo := false
			if path.BodyDirec == HeadBA && path.GetSource().Id == path.NodeA.Id {
				isTailGo = true

			} else if path.BodyDirec == HeadAB && path.GetSource().Id == path.NodeB.Id {
				isTailGo = true
			}
			if !isTailGo {
				dtheta1 := angles.NormalizeAngle(angles.Deg2Rad(lp.RobotAng - float64(path.PathEndAng)))
				dtheta2 := angles.NormalizeAngle(angles.Deg2Rad(lp.RobotAng - float64(path.PathEndAng) - 180.0))
				if math.Abs(dtheta1) > math.Pi/18 && math.Abs(dtheta2) > math.Pi/18 {
					isBackRotateConflict = path.PathPolygon.pathBlockCircle(float64(lp.CurrentNode.X), float64(lp.CurrentNode.Y), lp.BackRadius)
				}
			}
		}

		if config.Conf.UseHeadCatch && needCalc && !isBackRotateConflict {
			if path.RotateType == 0 {
				//判断当前车是否在工位
				dtheta1 := angles.NormalizeAngle(angles.Deg2Rad(lp.RobotAng - float64(path.PathEndAng)))
				dtheta2 := angles.NormalizeAngle(angles.Deg2Rad(lp.RobotAng - float64(path.PathEndAng) - 180.0))
				if math.Abs(dtheta1) > math.Pi/18 && math.Abs(dtheta2) > math.Pi/18 {

					if lp.CurrentNode.Type == NodeStation {
						//库位点前一个点，特殊处理
						retMaps := GetFrontNodes(lp.CurrentNode)
						for _, nodeFront := range retMaps {
							isBackRotateConflict = path.PathPolygon.pathBlockCircle(float64(nodeFront.X), float64(nodeFront.Y), lp.BackRadius)
							if isBackRotateConflict {
								break
							}
						}

					} else if IsConnectStation(lp.CurrentNode) {
						isBackRotateConflict = path.PathPolygon.pathBlockCircle(float64(lp.CurrentNode.X), float64(lp.CurrentNode.Y), lp.BackRadius)
					}

				}
			}
		}

	}

	isConflict, conflictPathId := lp.Paths.Conflict(copyPath)
	return isConflict || isRectangleConflict || isBackRotateConflict, conflictPathId
}

func (LocalPath) TableName() string {
	return "t_running_local_paths"
}

type ConflictModeType uint8

const (
	ConflictNone      ConflictModeType = 0 //不冲突
	ConflictPathMutex ConflictModeType = 1 //路径冲突
	ConflictOutline   ConflictModeType = 2 //轮廓冲突
)

//++允许路线对冲区域逻辑
type orderAreaPath struct {
	Index               int
	BindPathMutexAreaId string
	IsNotGo             bool   //局部路径对冲
	ConflictAgvId       string //记录冲突的编号
	ConflictTrafficPath *TrafficPath
	ConflictLocks       PathLocks
	ConflictMode        ConflictModeType
}

func (allNeedLocalPaths TrafficPaths) GetAllowPathMuteuxAbout(allApprovedLocalPaths []LocalPath, currentAgvId string) []orderAreaPath {
	//++允许路线对冲区域的分类处理
	allowMutexPathMap := make(map[string][]*TrafficPath, 0)
	allowOrderMutexAreaPath := make([]orderAreaPath, 0)

	IsContainElement := func(arr []orderAreaPath, bindPathMutexAreaId string) bool {
		for _, ele := range arr {
			if ele.BindPathMutexAreaId == bindPathMutexAreaId {
				return true
			}
		}
		return false
	}
	// hasPath := func(id int, paths []*TrafficPath) (*TrafficPath, bool) {
	// 	for _, p := range paths {
	// 		if p.Id == id {
	// 			return p, true
	// 		}
	// 	}
	// 	return nil, false
	// }

	IslocalPathMutex := func(otherApprovedPath *TrafficPath, trafficPath1 *TrafficPath) bool {
		//方向
		notA2B := false
		notB2A := false

		// if otherApprovedPath.Id == trafficPath1.Id {
		notA2B = notA2B || trafficPath1.Dir == DirectionB2A
		notB2A = notB2A || trafficPath1.Dir == DirectionA2B
		// }

		if notA2B && otherApprovedPath.Dir == DirectionA2B {
			//log.Infof("remove edge:%d to %d", l.NodeA.Id, l.NodeB.Id)
			return true
		}
		if notB2A && otherApprovedPath.Dir == DirectionB2A {
			//log.Infof("remove edge:%d to %d", l.NodeB.Id, l.NodeA.Id)
			return true
		}

		return false
	}
	//判断已经批复的局部路径,是否存在反向
	IsNoPathOutLineConflict := func(lp LocalPath, trafficPath1 *TrafficPath) (bool, PathLocks) {
		conflict1s := make(PathLocks, 0)
		isFindConflict := false

		if lp.Paths == nil || len(lp.Paths) == 0 {
			if lp.SpecialLocks != nil {
				if lp.SpecialLocks.Conflict(trafficPath1.AllBlocks()) {
					return true, conflict1s
				}
			}
			isFindConflict = lp.NodeRect.ConflictPolygon(trafficPath1.PathPolygon)
			if isFindConflict {
				conflict1s = append(conflict1s, trafficPath1.AllBlocks()...)
				return isFindConflict, conflict1s
			}
			//判断所点

		}
		return false, conflict1s
	}

	IsApprovedPathConfict := func(lp LocalPath, need *TrafficPath) (bool, PathLocks) {
		conflict1s := make(PathLocks, 0)
		isFindConflict := false
		for _, otherApprovedPath := range lp.Paths {
			if otherApprovedPath.Id == need.Id {
				isFindConflict = IslocalPathMutex(otherApprovedPath, need)
			}
			if isFindConflict {
				conflict1s = append(conflict1s, otherApprovedPath.AllBlocks()...)
				return true, conflict1s
			}
		}
		return false, conflict1s
	}
	GetConflict := func(need1 *TrafficPath) (PathLocks, bool, bool, string) {
		pathLocks := make(PathLocks, 0)
		for _, approved := range allApprovedLocalPaths {
			//判断所有批复的路径，除了自己
			if approved.Sn == currentAgvId {
				continue
			}
			isLocalPathMetux1, pathLock1s := IsApprovedPathConfict(approved, need1)
			if isLocalPathMetux1 {
				pathLocks = append(pathLocks, pathLock1s...)
				return pathLocks, true, false, approved.Sn
			}
			isLocalPathMetux2, pathLock2s := IsNoPathOutLineConflict(approved, need1)
			if isLocalPathMetux2 {
				pathLocks = append(pathLocks, pathLock2s...)
				return pathLocks, false, true, approved.Sn
			}
		}
		return pathLocks, false, false, ""
	}

	//赋值部分
	if len(allNeedLocalPaths) > 0 {
		//判断顺序进入局部路径的区域ID
		for idx, needPath := range allNeedLocalPaths {
			if needPath.BindPathMutexAreaId != "" && !IsContainElement(allowOrderMutexAreaPath, needPath.BindPathMutexAreaId) {
				var orderPath orderAreaPath
				orderPath = orderAreaPath{
					Index:               idx,
					BindPathMutexAreaId: needPath.BindPathMutexAreaId,
					IsNotGo:             false,
				}
				allowOrderMutexAreaPath = append(allowOrderMutexAreaPath, orderPath)
			}
		}
		//顺序找出需要经过的允许路线对冲的区域ID
		for _, path := range allNeedLocalPaths {
			if path.BindPathMutexAreaId != "" {
				_, find := allowMutexPathMap[path.BindPathMutexAreaId]
				if find {
					allowMutexPathMap[path.BindPathMutexAreaId] = append(allowMutexPathMap[path.BindPathMutexAreaId], path)
				} else {
					res1 := make([]*TrafficPath, 0)
					res1 = append(res1, path)
					allowMutexPathMap[path.BindPathMutexAreaId] = res1
				}
			}
		}

		//把每个节点当作一个整体部分来处理
		for i, mutexAreaPath := range allowOrderMutexAreaPath {
			//得到该允许路线对冲区域内部线路，判断是否允许路线对冲
			trafficPaths, ok := allowMutexPathMap[mutexAreaPath.BindPathMutexAreaId]
			if !ok || trafficPaths == nil || len(trafficPaths) < 1 {
				continue
			}
			//顺序遍历当前允许路线对冲区域的路径顺序
			isLocalPathMetux := false
			for _, need := range trafficPaths {
				//判断当前需要的路径和已批复的路径是否冲突
				pathLocks, isLocalPathMetux1, isLocalPathMetux2, conflictSn := GetConflict(need)
				isLocalPathMetux = isLocalPathMetux1 || isLocalPathMetux2
				if isLocalPathMetux {
					log.Errorf("robot:%s  isLocalPathMetux1:%t  isLocalPathMetux2:%t ", currentAgvId, isLocalPathMetux1, isLocalPathMetux2)
					allowOrderMutexAreaPath[i].ConflictLocks = pathLocks
					allowOrderMutexAreaPath[i].ConflictAgvId = conflictSn
					allowOrderMutexAreaPath[i].ConflictTrafficPath = need
					if isLocalPathMetux1 {
						allowOrderMutexAreaPath[i].ConflictMode = ConflictPathMutex
					} else if isLocalPathMetux2 {
						allowOrderMutexAreaPath[i].ConflictMode = ConflictOutline
					}
					allowOrderMutexAreaPath[i].IsNotGo = isLocalPathMetux
					break
				}
			}
		}
	}
	//返回值
	return allowOrderMutexAreaPath

}
